package ${projectDomain}.language.fovasala;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

@Component
@Api(value="表单验证标准语言代码解析", author="unswift", date="2023-06-08", version="1.0.0")
public class FovasalaCodeParse {

	@ApiMethod(value="解析表单验证标准语言行代码", params={@ApiField("行代码")}, returns=@ApiField("系统能够识别的代码列表"))
	public List<FovasalaCode> parse(String lineCode){
		StringTokenizer tokens = new StringTokenizer(lineCode, FovasalaSymbolEnum.ALL.getSymbol(), true);//拆分
		return parseToken(tokens, null, null, null);
	}
	
	@ApiMethod(value="根据特定字符拆分的行代码对象解析行代码", params={@ApiField("拆分的行代码对象"), @ApiField("父代码对象"), @ApiField("开始符号"), @ApiField("结束符号")})
	private List<FovasalaCode> parseToken(StringTokenizer tokens, FovasalaCode fovasalaCode, String startSymbol, String endSymbol){
		String token, codeItem="";
		List<FovasalaCode> childList=new ArrayList<FovasalaCode>();
		while(tokens.hasMoreElements()){
			token=tokens.nextToken();
			if(FovasalaSymbolEnum.BE_NOT.getSymbol().equals(token)){//!
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(new FovasalaCode(FovasalaSymbolEnum.BE_NOT, null));
				codeItem=matchNextCompare(tokens, codeItem, childList, token);
			}else if(FovasalaSymbolEnum.EQUAL.getSymbol().equals(token)){//=
				if(ObjectUtils.isNotEmpty(codeItem)) {
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(new FovasalaCode(FovasalaSymbolEnum.EQUAL, null));
				codeItem=matchNextCompare(tokens, codeItem, childList, token);
			}else if(FovasalaSymbolEnum.GT.getSymbol().equals(token)){//>
				if(ObjectUtils.isNotEmpty(codeItem)) {
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(new FovasalaCode(FovasalaSymbolEnum.GT, null));
				codeItem=matchNextCompare(tokens, codeItem, childList, token);
			}else if(FovasalaSymbolEnum.LT.getSymbol().equals(token)){//<
				if(ObjectUtils.isNotEmpty(codeItem)) {
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(new FovasalaCode(FovasalaSymbolEnum.LT, null));
				codeItem=matchNextCompare(tokens, codeItem, childList, token);
			}else if(FovasalaSymbolEnum.BRACKET_LEFT.getSymbol().equals(token)){//(
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				FovasalaCode fovasalaCodeChild = new FovasalaCode(FovasalaSymbolEnum.BRACKET_LEFT, null);
				childList.add(fovasalaCodeChild);
				parseToken(tokens, fovasalaCodeChild, FovasalaSymbolEnum.BRACKET_LEFT.getSymbol(), FovasalaSymbolEnum.BRACKET_RIGHT.getSymbol());
				codeItem="";
			}else if(FovasalaSymbolEnum.ADD.getSymbol().equals(token)){//+
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				codeItem=matchNextOperator(tokens, codeItem, childList, token);
				childList.add(new FovasalaCode(FovasalaSymbolEnum.ADD, null));
			}else if(FovasalaSymbolEnum.SUB.getSymbol().equals(token)){//-
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				codeItem=matchNextOperator(tokens, codeItem, childList, token);
				childList.add(new FovasalaCode(FovasalaSymbolEnum.SUB, null));
			}else if(FovasalaSymbolEnum.MUL.getSymbol().equals(token)){//*
				if(ObjectUtils.isNotEmpty(codeItem)) {
					childList.add(new FovasalaCode(null, codeItem));
				}
				codeItem=matchNextOperator(tokens, codeItem, childList, token);
				childList.add(new FovasalaCode(FovasalaSymbolEnum.MUL, null));
			}else if(FovasalaSymbolEnum.DIV.getSymbol().equals(token)){///
				if(ObjectUtils.isNotEmpty(codeItem)) {
					childList.add(new FovasalaCode(null, codeItem));
				}
				codeItem=matchNextOperator(tokens, codeItem, childList, token);
				childList.add(new FovasalaCode(FovasalaSymbolEnum.DIV, null));
			}else if(FovasalaSymbolEnum.STRING.getSymbol().equals(token)){//"
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(findEndStringSymbol(tokens));
				codeItem="";
			}else if(FovasalaSymbolEnum.STRING2.getSymbol().equals(token)){//'
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(findEndString2Symbol(tokens));
				codeItem="";
			}else if(FovasalaSymbolEnum.METHOD_MULTI_PARAMETER.getSymbol().equals(token)){
				if(ObjectUtils.isNotEmpty(codeItem)){
					childList.add(new FovasalaCode(null, codeItem));
				}
				childList.add(new FovasalaCode(FovasalaSymbolEnum.METHOD_MULTI_PARAMETER, null));
				codeItem="";
			}else if(token.equals(endSymbol)){
				break;//如果找到结束符号，则结束
			}else{
				codeItem+=token;
			}
		}
		if(ObjectUtils.isNotEmpty(codeItem)){
			childList.add(new FovasalaCode(null, codeItem));
		}
		if(ObjectUtils.isNotEmpty(fovasalaCode) && ObjectUtils.isNotEmpty(childList)){
			fovasalaCode.setChildCodeList(childList);
		}
		return childList;
	}
	
	@ApiMethod(value="分析下一个匹配的比较符", params={@ApiField("拆分后的代码枚举"), @ApiField("累加的代码"), @ApiField("当前代码逻辑列表"), @ApiField("匹配的符号")})
	private String matchNextCompare(StringTokenizer tokens, String codeItem, List<FovasalaCode> fovasalaCodeList, String symbol){
		if(tokens.hasMoreElements()){
			String token=tokens.nextToken();
			if(FovasalaSymbolEnum.EQUAL.getSymbol().equals(token)){//+=、-=、*=、/=
				if(FovasalaSymbolEnum.BE_NOT.getSymbol().equals(symbol)){
					fovasalaCodeList.get(fovasalaCodeList.size()-1).setSymbol(FovasalaSymbolEnum.NOT_EQUAL);
				}else if(FovasalaSymbolEnum.EQUAL.getSymbol().equals(symbol)){
					
				}else if(FovasalaSymbolEnum.GT.getSymbol().equals(symbol)){
					fovasalaCodeList.get(fovasalaCodeList.size()-1).setSymbol(FovasalaSymbolEnum.GTE);
				}else if(FovasalaSymbolEnum.LT.getSymbol().equals(symbol)){
					fovasalaCodeList.get(fovasalaCodeList.size()-1).setSymbol(FovasalaSymbolEnum.LTE);
				}
				codeItem="";
			}else if(FovasalaSymbolEnum.BRACKET_LEFT.getSymbol().equals(token)){//+(、-(、*(、/(
				FovasalaCode fovasalaCode = new FovasalaCode(FovasalaSymbolEnum.BRACKET_LEFT, null);
				fovasalaCodeList.add(fovasalaCode);
				parseToken(tokens, fovasalaCode, FovasalaSymbolEnum.BRACKET_LEFT.getSymbol(), FovasalaSymbolEnum.BRACKET_RIGHT.getSymbol());
				codeItem="";
			}else if(FovasalaSymbolEnum.STRING.getSymbol().equals(token)){//"
				fovasalaCodeList.add(findEndStringSymbol(tokens));
				codeItem="";
			}else if(FovasalaSymbolEnum.STRING2.getSymbol().equals(token)){//'
				fovasalaCodeList.add(findEndString2Symbol(tokens));
				codeItem="";
			}else{
				codeItem=token;
			}
		}else{
			throw ExceptionUtils.message("operator.symbol.end.must.having", symbol);
		}
		return codeItem;
	}
	
	@ApiMethod(value="分析下一个匹配的运算符", params={@ApiField("拆分后的代码枚举"), @ApiField("累加的代码"), @ApiField("当前代码逻辑列表"), @ApiField("匹配的符号")})
	private String matchNextOperator(StringTokenizer tokens, String codeItem, List<FovasalaCode> fovasalaCodeList, String symbol){
		if(tokens.hasMoreElements()){
			String token=tokens.nextToken();
			if(FovasalaSymbolEnum.EQUAL.getSymbol().equals(token)){//+=、-=、*=、/=
				fovasalaCodeList.add(new FovasalaCode(FovasalaSymbolEnum.EQUAL, null));
				fovasalaCodeList.add(new FovasalaCode(null, codeItem));
				codeItem="";
			}else if(symbol.equals(token)){//++或--
				ExceptionUtils.trueException(
						!FovasalaSymbolEnum.ADD.getSymbol().equals(symbol) && 
						!FovasalaSymbolEnum.SUB.getSymbol().equals(symbol)
						, "favasala.language.syntax.error", String.format("不支持的语法：%s", symbol+symbol));
				if(FovasalaSymbolEnum.ADD.getSymbol().equals(symbol)){
					fovasalaCodeList.get(fovasalaCodeList.size()-1).setSymbol(FovasalaSymbolEnum.ADD_ONE);
				}else if(FovasalaSymbolEnum.SUB.getSymbol().equals(symbol)){
					fovasalaCodeList.get(fovasalaCodeList.size()-1).setSymbol(FovasalaSymbolEnum.SUB_ONE);
				}
				codeItem="";
			}else if(FovasalaSymbolEnum.BRACKET_LEFT.getSymbol().equals(token)){//+(、-(、*(、/(
				FovasalaCode fovasalaCode = new FovasalaCode(FovasalaSymbolEnum.BRACKET_LEFT, null);
				fovasalaCodeList.add(fovasalaCode);
				parseToken(tokens, fovasalaCode, FovasalaSymbolEnum.BRACKET_LEFT.getSymbol(), FovasalaSymbolEnum.BRACKET_RIGHT.getSymbol());
				codeItem="";
			}else if(FovasalaSymbolEnum.STRING.getSymbol().equals(token)){//"
				fovasalaCodeList.add(findEndStringSymbol(tokens));
				codeItem="";
			}else if(FovasalaSymbolEnum.STRING2.getSymbol().equals(token)){//'
				fovasalaCodeList.add(findEndString2Symbol(tokens));
				codeItem="";
			}else{
				codeItem=token;
			}
		}else{
			throw ExceptionUtils.message("operator.symbol.end.must.having", symbol);
		}
		return codeItem;
	}
	
	@ApiMethod(value="查找结束的双引号", params=@ApiField("拆分后的代码枚举"))
	private FovasalaCode findEndStringSymbol(StringTokenizer tokens) {
		String findToken="";
		String string="";
		while(tokens.hasMoreTokens() && (string.endsWith("\\\"") || !"\"".equals(findToken))){
			string += findToken;
			findToken = tokens.nextToken();
		}
		return new FovasalaCode(FovasalaSymbolEnum.STRING, string);
	}
	
	@ApiMethod(value="查找结束的单引号", params=@ApiField("拆分后的代码枚举"))
	private FovasalaCode findEndString2Symbol(StringTokenizer tokens) {
		String findToken="";
		String string="";
		while(tokens.hasMoreTokens() && (string.endsWith("\\'") || !"'".equals(findToken))){
			string += findToken;
			findToken = tokens.nextToken();
		}
		return new FovasalaCode(FovasalaSymbolEnum.STRING, string);
	}
	
}
